package com.wan37.logic.listener;

import com.wan37.logic.listener.annotation.EventHandler;
import com.wan37.logic.listener.annotation.Listener;
import com.wan37.logic.listener.event.BaseGameEvent;
import com.wan37.logic.listener.event.EventType;
import com.wan37.logic.utils.ClassScanner;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author : luoyong
 * @date : 2020-06-29 10:11
 **/
public class ListenerManager {
    public final static ListenerManager instance = new ListenerManager();

    public static ListenerManager getInstance() {
        return instance;
    }

    private Map<String, Method> map = new HashMap<>();

    private final String SCAN_PATH = "com.wan37.logic.listener.handler";

    public void init() {
        Set<Class<?>> listeners = ClassScanner.listClassesWithAnnotation(SCAN_PATH, Listener.class);

        for (Class<?> listener : listeners) {
            try {
                Object handler = listener.newInstance();
                Method[] methods = listener.getDeclaredMethods();
                for (Method method : methods) {
                    EventHandler mapperAnnotation = method.getAnnotation(EventHandler.class);
                    if (mapperAnnotation != null) {
                        EventType[] eventTypes = mapperAnnotation.value();
                        for (EventType eventType : eventTypes) {
                            EventDispatcher.getInstance().registerEvent(eventType, handler);
                            map.put(getKey(handler, eventType), method);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 分发给具体监听器执行
     *
     * @param handler
     * @param event
     */
    public void fireEvent(Object handler, BaseGameEvent event) {
        try {
            Method method = map.get(getKey(handler, event.getEventType()));
            method.invoke(handler, event);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String getKey(Object handler, EventType eventType) {
        return handler.getClass().getName() + "-" + eventType.toString();
    }
}
